package com.tedu.springboot2302.controller;

import com.tedu.springboot2302.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 当前类用于处理与用户相关的业务操作
 */
@Controller
public class UserController {
    private static File userDir;

    static {
        userDir = new File("./users");
        if (!userDir.exists()) {
            userDir.mkdirs();
        }
    }

    /*
        在reg.html页面上点击注册按钮,测试是否可以调用到当前reg方法.
        如果点击后页面上是"大白板"就说明对了,如果报错404则说明错误了.
        错误的原因可能是:
        1:浏览器上请求reg.html页面时,端口号是否为8080,不能使用63342这个端口!
          63342端口相当于是本地打开页面,不走我们的服务器
        2:当前UserController类所在的包controller是否与启动类在同一个包里
          SpringBoot的要求是必须放在与启动类SpringBoot2302Application所在同一个包中
        3:UserController类上是否添加了注解@Controller
          reg方法上是否添加了注解@RequestMapping,并且注解中传入的参数是否与reg.html页面
          上form表单中action的值相同.不仅相同,径路是否都是从"/"开始的.
          比如"/regUser"
        4:修改后服务器是否重启?浏览器是否重新刷新了?每次修改java代码后服务器要重启.每次修改了
          网页后不仅要重启服务器,浏览器也要刷新才可以.
     */
    @RequestMapping("/regUser")
    public void reg(HttpServletRequest request, HttpServletResponse response) {
        /*
            HttpServletRequest称为请求对象,内容表达的是浏览器发送过来的所有数据
            HttpServletResponse称为响应对象,内容表达的是我们处理完业务后给浏览器回复的内容

            处理业务的大致过程:
            1:通过请求对象获取浏览器发送过来的信息(比如表单中用户输入的注册信息)
            2:通过获取的信息进行响应的业务处理
            3:通过设置响应对象将处理结果回馈给浏览器
         */
        System.out.println("开始处理用户注册!!!!!!!!!!!!!!!");
        //获取表单提交的信息
        /*
            getParameter中的参数要与页面上表单中对应输入框的名字一致
            例如:
             String username = request.getParameter("username");
                                                     ^^^^^^^^
             应当对应的是reg.html页面上
             <input type="text" name="username">
                                      ^^^^^^^^
         */
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String nickname = request.getParameter("nickname");
        String ageStr = request.getParameter("age");
        /*
            获取参数后,可能出现的情况:
            1:与输入框中输入的信息一致,则是正常的
            2:如果是空字符串,说明页面上该输入框没有输入信息
            3:如果是null,说明没有获取到这个参数,原因:
              getParameter()中的参数与页面上对应输入框name属性的值不一致导致.
         */
        System.out.println(username + "," + password + "," + nickname + "," + ageStr);

        //对浏览器提交的数据进行必要的验证
        if (username == null || username.isEmpty() ||
                password == null || password.isEmpty() ||
                nickname == null || nickname.isEmpty() ||
                ageStr == null || ageStr.isEmpty() ||
                !ageStr.matches("[0-9]+")) {
            //直接给用于响应一个错误的提示页面
            try {
                response.sendRedirect("/reg_info_error.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        //验证通过后,就要将该用户信息保存在服务端
        /*
            将用户提交的注册信息以User实例形式表示.
            然后将该User实例序列化到文件中做长久保存.
         */
        int age = Integer.parseInt(ageStr);
        User user = new User(username, password, nickname, age);
//        File file = new File("./users/"+username+".obj");
        //第一个参数的File对象表示当前文件在哪个目录中
        File file = new File(userDir, username + ".obj");

        //首先判断该文件是否已经存在了,存在则说明此为重复用户
        if (file.exists()) {
            try {
                response.sendRedirect("/have_user.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        try (
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
        ) {
            oos.writeObject(user);

            response.sendRedirect("/reg_success.html");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/loginUser")
    public void login(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("开始处理用户登录");
        //1获取表单信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //必要的验证
        if (username == null || username.isEmpty() ||
                password == null || password.isEmpty()) {
            try {
                response.sendRedirect("/login_info_error.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        //用当前登录用户的用户名去users目录下找他的注册信息
        File file = new File(userDir, username + ".obj");
        if (file.exists()) {//文件存在则说明该用户注册过
            //反序列化该文件并得到曾经该用户的注册信息
            try (
                    FileInputStream fis = new FileInputStream(file);
                    ObjectInputStream ois = new ObjectInputStream(fis);
            ) {
                //从文件中反序列化回来的对象,应当是上面reg方法曾经保存的该用户的注册信息
                User user = (User) ois.readObject();
                //比较注册时输入的密码与本次登录时输入的密码是否一致
                if (user.getPassword().equals(password)) {
                    //密码一致则表示登录成功
                    response.sendRedirect("/login_success.html");
                } else {
                    //登录失败
                    response.sendRedirect("/login_fail.html");
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }

        } else {//文件不存在说明这不是一个注册用户
            try {
                response.sendRedirect("/login_fail.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @RequestMapping("/userList")
    public void userList(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("开始处理显示用户列表");

        //将users目录下的所有用户信息读取出来，存入一个集合备用
        List<User> userList = new ArrayList<>();

        //获取users目录下的所有obj文件
        File[] subs = userDir.listFiles(f -> f.getName().endsWith(".obj"));

        //遍历每一个obj文件并反序列化其中保存的User对象，最后存入userList集合
        for (File sub : subs) {
            try (FileInputStream fis = new FileInputStream(sub);
                 ObjectInputStream ois = new ObjectInputStream(fis);
            ) {
                User user = (User) ois.readObject();
                userList.add(user);
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        //给浏览器发送了一个地址,让浏览器重新访问这个位置
        //response.sendRedirect("xxx");

        //在获取输出流前设置字符集
        response.setContentType("text/html;charset=utf-8");
        try {
            //通过响应对象获取一个输出流，使用该流写出的内容会发送给浏览器
            PrintWriter pw = response.getWriter();
            pw.println("<!DOCTYPE html>");
            pw.println("<html lang=\"en\">");
            pw.println("<head>");
            pw.println("<meta charset=\"UTF-8\">");
            pw.println("<title>用户列表</title>");
            pw.println("</head>");
            pw.println("<body>");
            pw.println("<center>");
            pw.println("<h1>用户列表</h1>");

            pw.println("<table border='1'>");

            pw.println("<tr>");
            pw.println("<td>用户名</td>");
            pw.println("<td>密码</td>");
            pw.println("<td>昵称</td>");
            pw.println("<td>年龄</td>");
            pw.println("</tr>");

            for (User user : userList) {
                pw.println("<tr>");
                pw.println("<td>" + user.getUsername() + "</td>");
                pw.println("<td>" + user.getPassword() + "</td>");
                pw.println("<td>" + user.getNickname() + "</td>");
                pw.println("<td>" + user.getAge() + "</td>");
                pw.println("</tr>");
            }

            pw.println("</table>");

            pw.println("</center>");
            pw.println("</body>");
            pw.println("</html>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
